package edu.jhu.cs.oose.scheduleit.services;

import java.util.List;

import edu.jhu.cs.oose.scheduleit.services.impl.DataBaseException;
import edu.jhu.cs.oose.scheduleit.util.Attribute;
import edu.jhu.cs.oose.scheduleit.util.Filter;
import edu.jhu.cs.oose.scheduleit.util.JoinStatus;
import edu.jhu.cs.oose.scheduleit.vo.Group;
import edu.jhu.cs.oose.scheduleit.vo.User;
import edu.jhu.cs.oose.scheduleit.vo.UserInfo;

/**
 * An interface for service related to group
 * @author oose_group2
 *
 */
public interface GroupService {
	
	/**
	 * Create a new group
	 * @param user	The user who creates the new group
	 * @param attribute	The attribute of the new group
	 * @return	The new group created
	 * @throws DataBaseException	If a DataBaseException occurred
	 */
	public Group createGroup(User user, Attribute attribute) throws DataBaseException;
	
	/**
	 * Update the information of a certain group
	 * @param group	The group going to be updated
	 * @throws DataBaseException	If a DataBaseException occurred
	 */
	public void updateGroup(Group group) throws DataBaseException;

	/**
	 * Join the group
	 * @param group the group in which the user wants to join 
	 * @param user the user who wants to join the group
	 * @return return JoinStatus.Joined if the group accept the user or return JoinStatus.Applied if the decision hasn't be made, return null
	 * @throws DataBaseException	If a DataBaseException occurred
	 */
	public JoinStatus joinGroup(Group group, User user) throws DataBaseException;

	/**
	 * Quit the group
	 * @param group the group which the user wants to quit 
	 * @param user user the user who wants to quit the group
	 * @throws DataBaseException	If a DataBaseException occurred
	 */
	public void quitGroup(Group group, User user) throws DataBaseException;
	

	/**
	 * Get the groups which are fulfill with the given condition from whole database.
	 * By assigning offset and limit, the method would return a part of of the fulfilled result
	 * @param filters the search condition
	 * @param offset it's the number to skip. If offset = 0, the return object is start from the first object. 
	 *             <br> If offset =1, the return object is start from the second object.
	 * @param limit it's the maximum return size. If limit <0 , means no limitation.
	 * @return a list of group
	 * @throws DataBaseException If there is any data base exception, an exception will be throw out
	 */
	public List<Group> getGroup(List<Filter> filters, int offest, int limit) throws DataBaseException;
	
	/**
	 * Calculate how may groups which are fulfill with the given condition from whole database.
	 * @param filters The search condition
	 * @return The number of how many groups satisfying the given conditions 
	 * @throws DataBaseException If there is any data base exception, an exception will be throw out
	 */
	public int getGroupCount(List<Filter> filters) throws DataBaseException;

	/**
	 * Retrieve the group with certain id
	 * @param groupID	The id of the objective group
	 * @return	The group with certain id and hosted by certain user
	 * @throws DataBaseException	If a DataBaseException occurred
	 */
	public Group getGroup(int groupID) throws DataBaseException;
	
	/**
	 * Get the users which are fulfill with the given condition.
	 * By assigning offset and limit, the method would return a part of of the fulfilled result
	 * @param group the group to which users belong.
	 * @param status the join status. It could be ALL, APPLIED, JOINED
	 * @param offset it's the number to skip. If offset = 0, the return object is start from the first object. 
	 *             <br> If offset =1, the return event is start from the second event.
	 * @param limit it's the maximum return size. If limit <0 , means no limitation.
	 * @return a list of users
	 * @throws DataBaseException If there is any data base exception, an exception will be throw out
	 */
	public List<UserInfo> getUser(Group group, JoinStatus status, int offset, int limit) throws DataBaseException;
	/**
	 * Calculate how many users of certain type, belonged to a given group
	 * @param group	The group to which users belong.
	 * @param status	the join status. It could be ALL, APPLIED, JOINED
	 * @return	The number of how many users satisfying the given conditions
	 * @throws DataBaseException	If a DataBaseException occurred
	 */
	
	public int getUserCount(Group group, JoinStatus status) throws DataBaseException;
	
	/**
	 * Check if the user has joined the group 
	 * @param group the group which the user may joined
	 * @param user the user to query
	 * @return true if the user has joined, otherwise, false.
	 * @throws DataBaseException	If a DataBaseException occurred
	 */
	public boolean isJoined(Group group, User user) throws DataBaseException;
	
	/** 
	 * Check if the user has applied the group 
	 * @param group the group which the user may applied
	 * @param user the user to query
	 * @return true if the user has applied, otherwise, false.
	 * @throws DataBaseException	If a DataBaseException occurred
	 */
	public boolean isApplied(Group group, User user) throws DataBaseException;
	
	/** 
	 * Check if the user has been denied the group 
	 * @param group the group which the user may been denied
	 * @param user the user to query
	 * @return true if the user has applied, otherwise, false.
	 * @throws DataBaseException	If a DataBaseException occurred
	 */
	public boolean isDenied(Group group, User user) throws DataBaseException;
	
	/**
	 * Accept the user to join the group
	 * @param group the group which user applied
	 * @param user the user to be accepted
	 * @throws DataBaseException If a DataBaseException occurred
	 */
	public void accept(Group group, User user) throws DataBaseException;
	
	/**
	 * Reject the user to join the group
	 * @param group the group which user applied
	 * @param user the user to be rejected 
	 * @throws DataBaseException If a DataBaseException occurred
	 */
	public void reject(Group group, User user) throws DataBaseException;
}
